package com.wwdx.controller.rest;

import com.google.common.collect.Maps;
import com.wwdx.controller.base.BaseController;
import com.wwdx.model.WwdxPersonalModel;
import com.wwdx.model.dto.MobileDTO;
import com.wwdx.model.dto.PersonalDTO;
import com.wwdx.model.dto.ResultBean;
import com.wwdx.utils.ConstantHolder;
import com.wwdx.utils.HttpSender;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * @author liguoliang
 * @date 2017/7/20.
 */
@RestController
@RequestMapping("auth")
@Api(tags = "APP微信登录接口")
public class RestAppAuthController extends BaseController{

    /**
     * 登录
     */
    @RequestMapping("/login")
    @ApiIgnore
    public ResultBean login(PersonalDTO model){
        String phone = model.getPhone(),valid = model.getValid(),msgid = model.getMsgid();
        //手机验证码登录
        if (StringUtils.isNotBlank(phone) && StringUtils.isNotBlank(valid) && StringUtils.isNotBlank(msgid)){
            String key = String.format(ConstantHolder.MOBILE_OBJ, phone);
            String validCode = (String) hashOperations.get(key, msgid);
            if (!valid.equals(validCode)){
                return renderError("验证码错误");
            }
            return renderSuccess(wwdxPersonalService.executePersonalInfo(phone));
        }
        //微信登录
        return renderSuccess(wwdxPersonalService.executePersonalInfo(model));
    }

    /**
     * 发送短信
     * @param mobile 手机号
     */
    @RequestMapping("/sendmsg")
    @ApiOperation(value = "发送短信",httpMethod = "GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "mobile",value = "手机号",required = true)
    })
    public ResultBean sendmsg(String mobile){
        logger.info("发送短信:{}",mobile);
        String reg = "(((13[0-9]{1})|(15[0-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\\d{8})";
        boolean matches = Pattern.compile(reg).matcher(mobile).matches();
        if (matches){
            return renderSuccess(this.sendSMS(mobile));
        }
        return renderError("手机号格式不正确");
    }

    private MsgInfo sendSMS(String mobile){
        StringBuilder valid = new StringBuilder();
        int m = 6,n = 10;
        for (int i = 0; i < m; i++) {valid.append(RandomUtils.nextInt(0, n));}
        String content = String.format(ConstantHolder.Constant.SMS_CONTENT,valid);
        String result = new HttpSender().batchSend(mobile,content);
        String[] str = StringUtils.split(result, ',');
        if (str != null){
            String time = str[0];
            String[] sts = StringUtils.split(str[1], '\n');
            String msgid = sts[1];
            String key = String.format(ConstantHolder.MOBILE_OBJ, mobile);
            hashOperations.put(key,msgid,valid.toString());
            return new MsgInfo(msgid, time);
        }
        return null;
    }

    /**
     * 保存手机号
     * @param userid  用户ID
     * @param mobile  手机号
     * @param valid   短信验证码
     * @param msgid   短信ID，用于验证短信的唯一标识
     */
    @RequestMapping("/save/mobile")
    @ApiOperation(value = "保存手机号",httpMethod = "POST")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userid",value = "用户ID",required = true),
            @ApiImplicitParam(name = "mobile",value = "手机号",required = true),
            @ApiImplicitParam(name = "valid",value = "短信验证码",required = true),
            @ApiImplicitParam(name = "msgid",value = "短信ID",required = true)
    })
    public ResultBean save(Long userid, String mobile, String valid, String msgid){
        String key = String.format(ConstantHolder.MOBILE_OBJ, mobile);
        String validCode = (String) hashOperations.get(key, msgid);
        if (!valid.equals(validCode)){
            return renderError("验证码错误");
        }
        WwdxPersonalModel wwdxPersonalModel = wwdxPersonalService.getById(userid);
        wwdxPersonalModel.setPhone(mobile);
        wwdxPersonalModel.setGmtModified(new Date());
        wwdxPersonalService.update(wwdxPersonalModel);
        return renderSuccess();
    }

    /**
     * 手机号登录
     */
    @RequestMapping("/mobile/login")
    @ApiIgnore
    public ResultBean login(@Valid MobileDTO model, BindingResult result){
        logger.info("手机号登录:{}",model);
        //错误验证信息
        if (result.hasErrors()){
            return isErrors(result);
        }

        String phone = model.getPhone();
        //008
        String md5Pwd = "a13ee062eff9d7295bfc800a11f33704";
        String tel = "15163583568";
        String msg;
        boolean validate = new Md5Hash(model.getPassword()).toHex().equalsIgnoreCase(md5Pwd);
        if (!validate && !Objects.equals(tel,phone)){
            msg = "登录失败";
            return renderError(msg);
        }
        long userid = 10093L;
        WwdxPersonalModel wwdxPersonalModel = wwdxPersonalService.getById(userid);
        String token = getUUID().toUpperCase();
        wwdxPersonalModel.setToken(token);
        //通过token保存用户信息
        String key = String.format(ConstantHolder.USER_OBJ, token);
        valueOperations.set(key,model);
        //token有效期两小时
        redisTemplate.expire(key, 2 * 60 * 60, TimeUnit.SECONDS);
        //通过unionid保存token信息
        String userToken = String.format(ConstantHolder.USER_TOKEN, wwdxPersonalModel.getUnionId());
        valueOperations.set(userToken,token);
        redisTemplate.expire(userToken, 2 * 60 * 55, TimeUnit.SECONDS);
        return renderSuccess(wwdxPersonalModel);
    }

    /**
     * 错误验证信息
     */
    private ResultBean isErrors(BindingResult result){
        ResultBean resultBean = new ResultBean();
        Map<String, String> errors = this.getErrors(result);
        resultBean.setStatus(ResultBean.FAIL);
        resultBean.setMessage("error");
        resultBean.setData(errors);
        return resultBean;
    }

    private Map<String, String> getErrors(BindingResult result) {
        Map<String, String> map = Maps.newHashMapWithExpectedSize(10);
        List<FieldError> list = result.getFieldErrors();
        for (FieldError error : list) {
            map.put(error.getField(), error.getDefaultMessage());
        }
        return map;
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private class MsgInfo implements Serializable {
        private String msgid;
        private String time;
    }
}